package org.bronycorps.mlptss.domain.model;

import java.util.ArrayList;
import java.util.List;

import org.bronycorps.mlptss.domain.model.event.StateChangeEvent;
import org.bronycorps.mlptss.domain.model.event.StateChangeEventListener;
import org.bronycorps.mlptss.manager.TrajectFactory.MissileTrajectType;
import org.bronycorps.mlptss.manager.preferences.GameConfiguration;
import org.bronycorps.mlptss.utils.AnimationCache;
import org.bronycorps.mlptss.utils.DrawableAnimation;

import com.badlogic.gdx.math.Vector2;

public class Missile extends AbstractActorModel {

	public static class MissileTraject {
		private Vector2 startPoint, destinationPoint, waypoint;
		private MissileTrajectType trajectType;

		public MissileTraject(MissileTrajectType trajectType,
				Vector2 startPoint, Vector2 waypoint, Vector2 destinationPoint) {
			super();
			this.trajectType = trajectType;
			this.startPoint = startPoint;
			this.waypoint = waypoint;
			this.destinationPoint = destinationPoint;
		}

		public Vector2 getDestinationPoint() {
			return this.destinationPoint;
		}

		public Vector2 getStartPoint() {
			return this.startPoint;
		}

		public MissileTrajectType getTrajectType() {
			return this.trajectType;
		}

		public Vector2 getWaypoint() {
			return this.waypoint;
		}
	}

	public enum State {
		EXPLODE, NORMAL
	}

	private float angle;

	private int life;
	private final Player owner;

	final private int rebounceCount;

	private State state = State.NORMAL;
	private List<StateChangeEventListener> stateChangeListeners = new ArrayList<StateChangeEventListener>();
	private MissileTraject traject;

	public Missile(Player owner, int rebounceCount) {
		super();
		this.owner = owner;
		this.life = GameConfiguration.getInstance().getMissileLife();
		this.rebounceCount = rebounceCount;
	}

	public boolean addListener(StateChangeEventListener listener) {
		return this.stateChangeListeners.add(listener);
	}

	public synchronized void fireStateChangeEvent() {
		for (StateChangeEventListener listener : this.stateChangeListeners) {
			listener.onStateChange(new StateChangeEvent(this));
		}
	}

	public float getAngle() {
		return this.angle;
	}

	public DrawableAnimation getDefaultAnimation() {
		return AnimationCache.getInstance().get(
				GameConfiguration.getInstance().getCurrentMod()
						.getAssetsConfiguration().getMissile()
						.getAnimationName());
	}

	@Override
	public int getLife() {
		return this.life;
	}

	public int getLifeColor() {
		return this.life;
	}

	public Player getOwner() {
		return this.owner;
	}

	public int getRebounceCount() {
		return this.rebounceCount;
	}

	public State getState() {
		return this.state;
	}

	public MissileTraject getTraject() {
		return this.traject;
	}

	public void hit(Bullet model) {
		this.life--;
		if (this.life <= 0) {
			setState(State.EXPLODE);
		}
	}

	public void hit(Enemy model) {
		this.life = 0;

		setState(State.EXPLODE);
	}

	public void hit(SpecialBullet model) {
		this.life = 0;

		setState(State.EXPLODE);
	}

	public boolean remove(Object listener) {
		return this.stateChangeListeners.remove(listener);
	}

	public void setLife(int life) {
		this.life = life;
	}

	@Override
	public void setPosition(float x, float y) {
		Vector2 v = new Vector2(x - this.position.x, y - this.position.y);
		this.angle = v.angle();

		super.setPosition(x, y);
	}

	@Override
	public void setPosition(Vector2 position) {
		Vector2 v = new Vector2(position).sub(this.position);
		this.angle = v.angle();

		super.setPosition(position);
	}

	public void setState(State state) {
		this.state = state;
		fireStateChangeEvent();
	}

	public void setTraject(MissileTraject traject) {
		this.traject = traject;
	}
}
